<?php
/**
 * CCrudPortlet class file.
 *
 * @author Lucas Vasconcelos <contato@lucasvasconcelos.com>
 * @copyright Copyright(c) 2010 Lucas Vasconcelos
 * @license BSD License http://www.lucasvasconcelos.com/yap/license
 * @link http://www.lucasvasconcelos.com/yap/
 * @version $Id: CCrudPortlet.php 21 2010-02-09 19:48:24Z contato@lucasvasconcelos.com $
 * @package yap.web.portlets
 */

Prado::using('yap.web.portlets.CCrudPortlet');
Prado::using('yap.helpers.CCtrlFinder');

/**
 * CCrudPortlet class.
 *
 * @author Lucas Vasconcelos <contato@lucasvasconcelos.com>
 * @version 1.0 $Revision: 21 $
 * @package yap.web.portlets
 */
abstract class CCrudPortlet extends CGridPortlet implements IPageCrud
{
	/**
	 * @var CCrudManager
	 */
	private $_crudManager=null;
	
	/**
	 * @var TActiveRecord
	 */
	private $_record=null;
	
	public function onSetupGrid($param)
	{
		parent::onSetupGrid($param);
		$this->{IPageGrid::GRID_ID}->OnItemCommand=array($this,'itemCommand');
	}
	
	/**
	 * Este método é invocado durante o estágio OnLoad, quando o usuário executa a ação 'CActionType::Create'.
	 * Este método dispara o evento 'OnCreate' para acionar os manipuladores de evento.
	 * Se sobreescrever este método, certifique-se de chamar a implementação da classe pai para que
	 * os manipuladores de evento sejam acionados.
	 * @param TEventParameter parâmetro do evento que deve ser passado para os manipuladores de evento.
	 */
	public function onCreate($param)
	{
		$this->setAction(CActionType::Create);
		$this->raiseEvent('OnCreate',$this,$param);
	}
	
	/**
	 * Este método é invocado durante o estágio OnLoad, quando o usuário executa a ação 'CActionType::Read'.
	 * Este método dispara o evento 'OnRead' para acionar os manipuladores de evento.
	 * Se sobreescrever este método, certifique-se de chamar a implementação da classe pai para que
	 * os manipuladores de evento sejam acionados.
	 * @param TEventParameter parâmetro do evento que deve ser passado para os manipuladores de evento.
	 */
	public function onRead($param)
	{
		$this->setAction(CActionType::Read);
		$this->raiseEvent('OnRead',$this,$param);
	}
	
	/**
	 * Este método é invocado durante o estágio OnLoad, quando o usuário executa a ação 'CActionType::Update'.
	 * Este método dispara o evento 'OnUpdate' para acionar os manipuladores de evento.
	 * Se sobreescrever este método, certifique-se de chamar a implementação da classe pai para que
	 * os manipuladores de evento sejam acionados.
	 * @param TEventParameter parâmetro do evento que deve ser passado para os manipuladores de evento.
	 */
	public function onUpdate($param)
	{
		$this->setAction(CActionType::Update);
		$this->raiseEvent('OnUpdate',$this,$param);
	}
	
	/**
	 * Este método é invocado durante o estágio OnLoad, quando o usuário executa a ação 'CActionType::Delete'.
	 * Este método dispara o evento 'OnDelete' para acionar os manipuladores de evento.
	 * Se sobreescrever este método, certifique-se de chamar a implementação da classe pai para que
	 * os manipuladores de evento sejam acionados.
	 * @param TEventParameter parâmetro do evento que deve ser passado para os manipuladores de evento.
	 */
	public function onDelete($param)
	{
		$this->setAction(CActionType::Delete);
		$this->raiseEvent('OnDelete',$this,$param);
	}
	
	/**
	 * Este método é invocado durante o estágio OnLoad, quando o usuário executa a ação 'CActionType::View'.
	 * Este método dispara o evento 'OnView' para acionar os manipuladores de evento.
	 * Se sobreescrever este método, certifique-se de chamar a implementação da classe pai para que
	 * os manipuladores de evento sejam acionados.
	 * @param TEventParameter parâmetro do evento que deve ser passado para os manipuladores de evento.
	 */
	public function onView($param)
	{
		$this->setAction(CActionType::View);
		$this->raiseEvent('OnView',$this,$param);
	}
	
	/**
	 * Este método geralmente é invocado durante o OnClick de um botão, quando o usuário deseja persistir as
	 * informações do formulário.
	 * Este método dispara o evento 'OnSave' para acionar os manipuladores de evento.
	 * Se sobreescrever este método, certifique-se de chamar a implementação da classe pai para que
	 * os manipuladores de evento sejam acionados.
	 * @param TEventParameter parâmetro do evento que deve ser passado para os manipuladores de evento.
	 */
	public function onSave($param)
	{
		$this->raiseEvent('OnSave',$this,$param);
	}
	
	/**
	 * Este método geralmente é invocado durante o OnClick de um botão, quando o usuário deseja persistir as
	 * informações do formulário.
	 * Este método dispara o evento 'OnBindFields' para acionar os manipuladores de evento.
	 * Se sobreescrever este método, certifique-se de chamar a implementação da classe pai para que
	 * os manipuladores de evento sejam acionados.
	 * @param TEventParameter parâmetro do evento que deve ser passado para os manipuladores de evento.
	 */
	public function onBindFields($param)
	{
		$this->raiseEvent('OnBindFields',$this,$param);
	}
	
	/**
	 * Set da propriedade Action.
	 * @param string deve ser um dos valores definidos no enum {@link CActionType}
	 */
	public function setAction($value)
	{
		$this->setViewState('Action',$value,CActionType::Read);
	}
	
	/**
	 * Get da propriedade Action.
	 * @return string
	 */
	public function getAction()
	{
		return $this->getViewState('Action',CActionType::Read);
	}
	
	/**
	 * @return TActiveRecord instancia contendo dados do registro selecionado.
	 */
	public function getRecord()
	{
		
		if($this->_record===null)
		{
			foreach($this->getFinder()->getRecordTableInfo()->PrimaryKeys as $name)
				$pks[]=$this->getKey($name);
			$this->_record=$this->getFinder()->findByPk($pks);
		}
		return $this->_record;
	}
	
	/**
	 * Implementação default.
	 * @see CPageGrid#getData($criteria)
	 */
	public function getData(TActiveRecordCriteria $criteria)
	{
		return $this->getFinder()->findAll($criteria);
	}
	
	/**
	 * @return CCrudManager
	 */
	public function getCrudManager()
	{
		if($this->_crudManager===null)
			$this->_crudManager=new CCrudManager($this);
		return $this->_crudManager;
	}
	
	/**
	 * Este método é chamado durante os eventos {@link onCreate OnCreate}, {@link onUpdate OnUpdate} e {@link onView OnView}
	 * Sobreescreva para adicionar sua própria rotina de inicialização.
	 */
	public function initForm()
	{
		foreach(CCtrlFinder::findAllById($this,'/'.IPageCrud::FIELD_PREFIX.'/') as $ctrl)
		{
			if($ctrl instanceof TTextBox)
				$ctrl->Text=null;
			if($ctrl instanceof TCheckBox)
				$ctrl->Checked=false;
			if($ctrl instanceof TDropDownList)
				$ctrl->SelectedValue=null;
		}
	}
	
	public function beforeSave(TActiveRecord $record)
	{
		foreach($this->getKeys() as $key => $value)
		{
			if(property_exists($record,$key))
				$record->{$key}=$value;
		}
	}
	
	public function afterSave(TActiveRecord $record) { }
	
	public function beforeDelete(TActiveRecord $record) { }
	
	public function afterDelete() { }
	
	public function itemCommand($sender,$param)
	{
		switch($param->CommandName)
		{
			case CActionType::Create:
				Prado::trace('CrudPortlet onCreate()','yap.web.portlets');
				$this->onCreate($param); break;
			case CActionType::Update:
				$this->setKey($this->grid->getDataKeyField(), $this->grid->DataKeys[$param->Item->ItemIndex]);
				Prado::trace('CrudPortlet onUpdate()','yap.web.portlets');
				$this->onUpdate($param); break;
			case CActionType::Delete:
				$this->setKey($this->grid->getDataKeyField(), $this->grid->DataKeys[$param->Item->ItemIndex]);
				Prado::trace('CrudPortlet onDelete()','yap.web.portlets');
				$this->onDelete($param); break;
			case CActionType::Save:
				Prado::trace('CrudPortlet onSave()','yap.web.portlets');
				$this->onSave($param); break;
			default:
				Prado::trace('CrudPortlet onRead()','yap.web.portlets');
				$this->onRead($param); break;
		}
	}
	
	public function allowedActions()
	{
		return array(CActionType::Create, CActionType::Update, CActionType::Delete);
	}
	
	public function reload()
	{
		Prado::trace('CrudPortlet onRead()','yap.web.portlets');
		$this->onRead(null);
	}
	
	/**
	 * Registra manipuladores de evento para eventos de CPageCrud.
	 */
	protected function registerEventHandlers()
	{
		parent::registerEventHandlers();
		$this->attachEventHandler('OnCreate',array('CCrudEventHandler','create'));
		$this->attachEventHandler('OnRead',array('CCrudPortletEventHandler','read'));
		$this->attachEventHandler('OnUpdate',array('CCrudEventHandler','update'));
		$this->attachEventHandler('OnDelete',array('CCrudEventHandler','delete'));
		$this->attachEventHandler('OnView',array('CCrudEventHandler','view'));
		$this->attachEventHandler('OnSave',array('CCrudEventHandler','save'));
		$this->attachEventHandler('OnBindFields',array('CCrudEventHandler','bindFields'));
	}
	
	/**
	 * Processa requisição do usuário.
	 * Sobreescreve implementação anterior. Para lhe dar com ações disponíveis para {@link CPageCrud}.
	 * @see CPageGrid#processRequest()
	 */
	protected function processRequest()
	{
		if(!$this->getPage()->getIsPostBack())
		{
			switch($this->getAction())
			{
				case CActionType::Create:
					Prado::trace('CrudPortlet onCreate()','yap.web.portlets');
					$this->onCreate(null); break;
				case CActionType::Update:
					Prado::trace('CrudPortlet onUpdate()','yap.web.portlets');
					$this->onUpdate(null); break;
				case CActionType::Delete:
					Prado::trace('CrudPortlet onDelete()','yap.web.portlets');
					$this->onDelete(null); break;
				case CActionType::View:
					Prado::trace('CrudPortlet onView()','yap.web.portlets');
					$this->onView(null); break;
				case CActionType::Read:
				default:
					//Prado::trace('CrudPortlet clearCriteria()','yap.web.portlets');
					//$this->getGridManager()->clearCriteria();
					
					Prado::trace('CrudPortlet onRead()','yap.web.portlets');
					$this->onRead(null); break;
			}
		}
		else
			Prado::trace('CrudPortlet postBack event.','yap.web.portlets');
	}
}


class CCrudPortletEventHandler extends CCrudEventHandler
{
	public static function read(IPageCrud $sender,$param)
	{
		Prado::trace('CCrudPortletEventHandler bindPortlet()','yap.web.portlets');
		$sender->getPage()->bindPortlet($sender);
		parent::read($sender,$param);
	}
}